class Router {
    
    constructor(arg) {
        // 路由跳转方法映射
        this.routeMap = {
            push: 'navigateTo',
            replace: 'redirectTo',
            replaceAll: 'reLaunch',
            pushTab: 'switchTab'
        }
        this.app = null;
        if (arg && arg.constructor !== Object) {
            return console.error(`Routing configuration must be an Object`)
        }
        Router.$root = this;
    }


    /**
     * 执行路由跳转
     */
    _pushTo() {
        return new Promise((resolve, reject) => {
            let { path, params, method } = this.tempRoute
            // 对首次进入页面执行路由守卫时如果放行，method path params都为空 此时应该直接中断流程，无需抛出异常
            if (!method && !path && !params) {
                return
            }
            let urlParams = '?'
            if (!path) {
                reject(new Error('参数page未填写'))
                return
            } else if (params && typeof(params) === 'object') {
                // 处理参数，转换为url字符串
                Object.keys(params).forEach(k => {
                    // 深度对象转为json字符串（包含数组）
                    if (typeof(params[k]) === 'object') {
                        if (params[k]) {
                            const json = JSON.stringify(params[k])
                            urlParams += `${k}=${json}&`
                        } else {
                            urlParams += `${k}=&`
                        }
                    } else if (typeof(params[k]) === 'number' || typeof(params[k]) === 'string' || typeof(params[k]) === 'boolean') {
                        // 基础值直接写入
                        urlParams += `${k}=${params[k]}&`
                    } else if (typeof(params[k]) === 'undefined') {
                        urlParams += `${k}=&`
                    }
                })
            }

            // 参数组装
            if (urlParams.length === 1) {
                urlParams = ''
            } else {
                urlParams = urlParams.substr(0, urlParams.length - 1)
            }

            // 设置路由跳转方式
            if (!method) {
                method = 'navigateTo'
            }
            if (this.routeMap[method]) {
                method = this.routeMap[method]
            }

            // 调用系统跳转方法
            uni[method]({
                url: path + urlParams,
                success: () => {
                    // 执行路由后置守卫
                    if (this._afterEach && typeof(this._afterEach) === 'function') {
                        this._afterEach.call(this, this.tempRoute, this.route)
                    }
                    // 更新路由信息
                    this.route = {
                        path: path + urlParams,
                        params: params || {},
                        page: path
                    }
                    this.tempRoute = null
                    resolve()
                },
                fail: (e) => {
                    reject(new Error('路由跳转失败！'))
                }
            })
        })
    }

    /**动态的导航到一个新 URL 保留浏览历史
     * navigateTo
     * @param {Object} rule
     */
    push(arg) {
        const rule = {
            method: 'navigateTo'
        }
        if (typeof(arg) === 'string') {
            rule.path = arg
        } else if (typeof(arg) === 'object') {
            rule.path = arg.path
            rule.params = arg.params
        }
        this.next(rule)
    }

    /**动态的导航到一个新 URL 关闭当前页面，跳转到的某个页面。
     * redirectTo
     * @param {Object} rule
     */
    replace(arg) {
        const rule = {
            method: 'redirectTo'
        }
        if (typeof(arg) === 'string') {
            rule.path = arg
        } else if (typeof(arg) === 'object') {
            rule.path = arg.path
            rule.params = arg.params
        }
        this.next(rule)
    }

    /**动态的导航到一个新 URL 关闭所有页面，打开到应用内的某个页面
     *  reLaunch
     * @param {Object} rule
     */
    replaceAll(arg) {
        const rule = {
            method: 'reLaunch'
        }
        if (typeof(arg) === 'string') {
            rule.path = arg
        } else if (typeof(arg) === 'object') {
            rule.path = arg.path
            rule.params = arg.params
        }
        this.next(rule)
    }

    /** 跳转Tabbar
     *  switchTab
     * @param {Object} rule
     */
    pushTab(arg) {
        const rule = {
            method: 'switchTab'
        }
        if (typeof(arg) === 'string') {
            rule.path = arg
        } else if (typeof(arg) === 'object') {
            rule.path = arg.path
            rule.params = arg.params
        }
        this.next(rule)
    }


    /**
     * 返回到指定层级页面上
     */
    back(delta = 1) {
        // 返回上级
        if (delta.constructor != Number) {
            this._errorHandler(new Error('返回层级参数必须是一个Number类型且必须大于0：'))
            return
        }
        uni.navigateBack({
            delta
        })
    }

    /**
     * 分发路由
     * @param {Object} args
     */
    _next() {
        return new Promise((resolve, reject) => {
            if (this._beforeEach && typeof(this._beforeEach) === 'function') {
                // 需要传给守卫 to from next
                this._beforeEach.call(this, this.tempRoute, this.route, resolve)
            } else {
                this._pushTo().catch(e => {
                    reject(e)
                })
            }
        })
    }

    next(args) {
        if (args) {
            // 保存临时数据
            if (typeof(args) === 'object') {
                this.tempRoute = {
                    // 第一次调用next一定存在method，后续循环调用可能不会存在，不存在时使用上次缓存的method
                    method: args.method || this.tempRoute.method,
                    path: args.page || args.path,
                    params: args.params
                }
            } else if (typeof(args) === 'string') {
                this.tempRoute = {
                    path: args
                }
            } else if (!args) {
                // 中断路由 args = false
                this.tempRoute = null
                return
            }

            if (!this.route) {
                this.route = {
                    path: '/' + getCurrentPages()[0].route
                }
            }

            this._next().then(args => {
                this.next(args)
            }).catch(e => {
                this.tempRoute = null
                this._errorHandler(e)
            })
        } else {
            this._pushTo().catch(e => {
                this.tempRoute = null
                this._errorHandler(e)
            })
        }
    }

    /**
     * 应用启动时执行一次路由检查（前置守卫，若通过则不做事情）
     */
    doBeforeHooks() {
        this.tempRoute = {}
        this.next({})
    }

    // 设置路由前置/后置守卫
    beforeEach(fn) {
        this._beforeEach = fn
    }
    afterEach(fn) {
        this._afterEach = fn
    }
    // 设置路由跳转错误处理
    onError(fn) {
        if (fn && typeof(fn) === 'function') {
            this._errorHandler = fn
        }
    }

    // 获取当前路由信息
    getCurrentRoute() {
        return this.route
    }

    /**
     * 返回APP数据
     * @return {[type]} [description]
     */
    setAdhibition(self) {
        this.app = self;
    }

}

// 路由对象属性定义
Router.$root = null
// 定义VM应用
Router.app = null
// 当前路由内容
Router.route = null
// 临时路由信息
Router.tempRoute = null
// 路由前置后置守卫
Router._beforeEach = null
Router._afterEach = null
// 路由跳转错误处理
Router._errorHandler = function(e) {
    console.error(e)
}

Router.install = function(Vue) {
    Vue.mixin({
        onLaunch: function() {},
        onLoad: function(props) {
            // //传入VM应用数据
            // Router.$root.setAdhibition(this)
            // // 首次进入页面时,缓存中不存在当前路由信息，需要初始化路由信息
            // if (!Router.$root.getCurrentRoute()) {
            //     const rt = {
            //         params: {},
            //         path: '/' + getCurrentPages()[0].route
            //     }
            //     if (props) {
            //         Object.keys(props).forEach(k => {
            //             // url转的对象全部都是字符串，需要识别其中的对象和基本数据类型
            //             try {
            //                 const obj = JSON.parse(props[k])
            //                 if (typeof(obj) === 'string') {
            //                     // 只有字符串还会是字符串，数字、布尔、数组均会转换为正常类型
            //                     rt.params[k] = props[k]
            //                 } else {
            //                     rt.params[k] = obj
            //                 }
            //             } catch (e) {
            //                 rt.params[k] = props[k]
            //             }
            //         })
            //     }
            //     Router.$root.route = rt
            //     // 执行路由前置守卫
            //     Router.$root.doBeforeHooks()
            // }
        }
    })
    // //设置路由函数
    // Object.defineProperty(Vue.prototype, "$router", {
    //     get: function() {
    //         return Router.$root
    //     }
    // })
    // Object.defineProperty(Vue.prototype, "$route", {
    //     get: function() {
    //         return Router.$root.getCurrentRoute()
    //     }
    // })
}

export default Router